package com.ericsson.enap.modules.topology.service.impl;

import com.csvreader.CsvReader;
import com.ericsson.enap.modules.monitor.mapper.CabServerMapper;
import com.ericsson.enap.modules.topology.entity.CabEdge;
import com.ericsson.enap.modules.topology.entity.CabNode;
import com.ericsson.enap.modules.topology.entity.CabServer;
import com.ericsson.enap.modules.topology.entity.CabSwitch;
import com.ericsson.enap.modules.topology.entity.Cvs;
import com.ericsson.enap.modules.monitor.mapper.CabSwitchMapper;
import com.ericsson.enap.modules.topology.mapper.CabTopologyEdgeMapper;
import com.ericsson.enap.modules.topology.mapper.CabTopologyNodeMapper;
import com.ericsson.enap.modules.topology.service.CabTopologySyncService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

//@Service
public class CabTopologySyncServiceImplbak implements CabTopologySyncService {
    @Autowired
    private CabServerMapper cabServerMapper;
    @Autowired
    private CabSwitchMapper cabSwitchMapper;
    @Autowired
    private CabTopologyEdgeMapper cabTopologyEdgeMapper;
    @Autowired
    private CabTopologyNodeMapper cabTopologyNodeMapper;

    @Override
    public void syncTopologyData() {
        List<CabServer> cabServerList = cabServerMapper.selectCabServer();
        List<CabSwitch> cabSwitchList = cabSwitchMapper.selectCabSwitch();
        List<Cvs> cvsList = readCsvFromDir("F:/csv",cabSwitchList,cabServerList);
        cvsList = removeInvalidRecord(cvsList);
        cvsList = removeRepeatRecord(cvsList);
        List<CabNode> nodeList = new ArrayList<>();
        List<CabEdge> edgeList = new ArrayList<>();
        parseData(cvsList,nodeList,edgeList);
        saveData(nodeList,edgeList);
    }

    /**
     * 保存数据
     * @param nodeList
     * @param edgeList
     */
    private void saveData(List<CabNode> nodeList,List<CabEdge> edgeList) {

        for(CabNode node : nodeList) {
            cabTopologyNodeMapper.insertTopologyNode(node);
        }
        for(CabEdge edge : edgeList) {
            edge.setOriginalVlan(StringUtils.join(edge.getVlan(),","));
            cabTopologyEdgeMapper.insertTopologyEdge(edge);
        }
    }


    /**
     * 将过滤好的数据解析成点集合与线集合
     * @param cvsList
     */
    private void parseData(List<Cvs> cvsList,List<CabNode> nodeList, List<CabEdge> edgeList) {

        List<Cvs> switchToSwitchList = new ArrayList<>(); //交换机-交换机
        for(Cvs cvs : cvsList) {
            if(cvs.getEdgeType() == 2) {
                //只找交换机-交换机的节点
                switchToSwitchList.add(cvs);
            }
        }
        for(Cvs cvs : cvsList) {
            if(cvs.getEdgeType() == 1) {
                //只找交换机-交换机的节点
                CabNode switchNode = createNode(cvs.getSourceId(),cvs.getLabId(),cvs.getSourceName(),2);
                CabNode serverNode = createNode(cvs.getTargetId(),cvs.getLabId(),cvs.getTargetName(),1);
                putNodeToList(nodeList,switchNode);
                putNodeToList(nodeList,serverNode);
               /* if(!nodeList.contains(switchNode)) nodeList.add(switchNode);
                if(!nodeList.contains(serverNode)) nodeList.add(serverNode);*/
                //实例化线
                CabEdge edge = createEdge(cvs);
                putEdgeToList(edgeList,edge);
                /*if(!edgeList.contains(edge)) edgeList.add(edge);*/
                recursionSearchSwitchAll(switchNode,switchToSwitchList,nodeList,edgeList,cvs.getLabId());
            }
        }


    }

    /*
     *
     * @param searchNode  要查询的节点
     * @param cvsList  需要解析的cvs 列表
     * switchToServerList 交换机-服务器链路
     * switchToSwitchList 交换机-交换机链路
     * @param nodeSet  查询到的节点
     * @param edgeSet  查询到的链路
     */
    private void recursionSearchSwitchAll(CabNode searchNode, List<Cvs> switchToSwitchList, List<CabNode> nodeList,List<CabEdge> edgeList, Integer labId) {

        boolean isSearchSwitch = false;  //查询到该交换机还有其他交换机相链接
        for(Cvs switchNode : switchToSwitchList) {
            //查询符合条件的交换机-交换机链路
            if(searchNode.getName().equalsIgnoreCase(switchNode.getSourceName())) {
                //查询到该交换机节点在该链路的source 位置
                isSearchSwitch  =  true;
                //保存交换机链路
                switchNode.setLabId(labId);
                CabEdge edge = createEdge(switchNode);
                if(!edgeList.contains(edge)) {
                    //edgeList.add(edge);  //加入交换机-交换机的链路
                    putEdgeToList(edgeList,edge);
                    //实例化两个交换机节点
                    CabNode switchNode1 = createNode(switchNode.getSourceId(),switchNode.getLabId(),switchNode.getSourceName(),2);
                    CabNode switchNode2 = createNode(switchNode.getTargetId(),switchNode.getLabId(),switchNode.getTargetName(),2);
                    putNodeToList(nodeList,switchNode1);
                    putNodeToList(nodeList,switchNode2);
                    /*if(!nodeList.contains(switchNode1)) nodeList.add(switchNode1);
                    if(!nodeList.contains(switchNode2)) nodeList.add(switchNode2);*/

                    //查询与target相链接的 下一个交换机
                    CabNode switchTargetNode = createNode(switchNode.getTargetId(),labId,switchNode.getTargetName(),2);
                    recursionSearchSwitchAll(switchTargetNode,switchToSwitchList,nodeList,edgeList,labId);
                }
            }

            if(searchNode.getName().equalsIgnoreCase(switchNode.getTargetName())) {
                //查询到该交换机节点在该链路的target 位置
                isSearchSwitch =  true;
                //保存交换机链路
                switchNode.setLabId(labId);
                CabEdge edge = createEdge(switchNode);
                if(!edgeList.contains(edge)) {

                    //edgeList.add(edge); //加入交换机-交换机的链路
                    putEdgeToList(edgeList,edge);
                    //实例化两个交换机节点
                    CabNode switchNode1 = createNode(switchNode.getSourceId(),switchNode.getLabId(),switchNode.getSourceName(),2);
                    CabNode switchNode2 = createNode(switchNode.getTargetId(),switchNode.getLabId(),switchNode.getTargetName(),2);
                    putNodeToList(nodeList,switchNode1);
                    putNodeToList(nodeList,switchNode2);
                    /*if(!nodeList.contains(switchNode1)) nodeList.add(switchNode1);
                    if(!nodeList.contains(switchNode2)) nodeList.add(switchNode2);*/

                    //查询与source相链接的 下一个交换机
                    CabNode switchSourceNode = createNode(switchNode.getSourceId(),labId,switchNode.getSourceName(),2);
                    recursionSearchSwitchAll(switchSourceNode,switchToSwitchList,nodeList,edgeList,labId);
                }
            }
        }
        if(!isSearchSwitch) {
            //没有查询到与交换机相连，递归结束
            return;
        }

    }

    private void putNodeToList(List<CabNode> nodeList,CabNode node) {
        if(!nodeList.contains(node)) nodeList.add(node);
    }

    private void putEdgeToList(List<CabEdge> edgeList,CabEdge edge) {
        if(!edgeList.contains(edge)) edgeList.add(edge);
    }


    private CabNode createNode(Long nodeId,Integer labId,String name,Integer type) {
        CabNode node = new CabNode();
        node.setId(nodeId);
        node.setLabId(labId);
        node.setName(name);
        node.setType(type);
        return node;

    }

    private CabEdge createEdge(Cvs cvs) {
        CabEdge edge = new CabEdge();
        edge.setLabId(cvs.getLabId());
        edge.setSourceId(cvs.getSourceId());
        edge.setSourcePort(cvs.getSourcePort());
        edge.setTargetId(cvs.getTargetId());
        edge.setTargetPort(cvs.getTargetPort());
        edge.setEdgeType(cvs.getEdgeType());
        edge.setOriginalVlan(cvs.getOriginalVlan());
        edge.setVlan(cvs.getVlan());
        return edge;
    }

    /*
     * 读取目中中csv文件并转换成集合
     * @param dir
     * @return
     */
    private List<Cvs> readCsvFromDir(String dir,List<CabSwitch> cabSwitchList,List<CabServer> cabServerList) {

        CsvReader reader = null;
        List<Cvs> cvsList = new ArrayList<>();
        File[] files = new File(dir).listFiles();
        for(File file : files) {
            try {
                // 用来保存数据
                reader = new CsvReader(new FileReader(file.getAbsolutePath()));
                while (reader.readRecord()) {
                    Cvs cvs = new Cvs();
                    String one = reader.get(0);
                    String two = reader.get(1);
                    String three = reader.get(2);
                    String four = reader.get(3);
                    String six = reader.get(5);
                    boolean isSuccess = setNode(cabSwitchList,cabServerList,cvs,one,two,three,four);
                    if(isSuccess) {
                        cvs.setVlan(conversArray(six));
                        cvs.setOriginalVlan(six);
                        cvsList.add(cvs);
                    }

                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if(null != reader) reader.close();
            }
        }

        return cvsList;
    }

    /**
     * 判断链路是否有效， 判断该链路 交换机-交换机  交换机-服务器， 并且赋值给对象
     * @param cabSwitchList
     * @param cabServerList
     * @param cvs
     * @param item
     */
    private boolean setNode(List<CabSwitch> cabSwitchList,List<CabServer> cabServerList,Cvs cvs,String ...item) {

        List<CabSwitch> switchList0 = cabSwitchList.stream().filter(s-> compareName(s.getName(),item[0])).collect(Collectors.toList());
        List<CabServer> serverList0 = cabServerList.stream().filter(s-> compareName(s.getName(),item[0])).collect(Collectors.toList());

        List<CabSwitch> switchList3 = cabSwitchList.stream().filter(s-> compareName(s.getName(),item[2])).collect(Collectors.toList());
        List<CabServer> serverList3 = cabServerList.stream().filter(s-> compareName(s.getName(),item[2])).collect(Collectors.toList());
        boolean successEdge = true;
        if(switchList0.size()>0) {
            //第一个交换机
            if(switchList3.size()>0) {
                //第一个交换机，第三个是交换机, 交换机按照名字比较，解决  a - b 和  b - a是同一条数据
                cvs.setEdgeType(2);
                int result = item[0].toUpperCase().compareTo(item[2].toUpperCase());
                String sourceName,sourcePort,targetName,targetPort;
                long sourceId,targetId;
                if(result < 0) {
                    sourceId = switchList0.get(0).getId();
                    targetId = switchList3.get(0).getId();
                    sourceName = item[0];
                    sourcePort = item[1];
                    targetName = item[2];
                    targetPort = item[3];
                } else {
                    sourceId = switchList3.get(0).getId();
                    targetId = switchList0.get(0).getId();
                    sourceName = item[2];
                    sourcePort = item[3];
                    targetName = item[0];
                    targetPort = item[1];
                }
                cvs.setSourceId(sourceId);
                cvs.setTargetId(targetId);
                cvs.setSourceName(sourceName);
                cvs.setSourcePort(sourcePort);
                cvs.setTargetName(targetName);
                cvs.setTargetPort(targetPort);

            } else {
                if(serverList3.size()>0) {
                    //第一个交换机，第三个是服务器
                    cvs.setEdgeType(1);
                    cvs.setSourceId(switchList0.get(0).getId());
                    cvs.setTargetId(serverList3.get(0).getId());
                    cvs.setLabId(serverList3.get(0).getLabId());
                    cvs.setSourceName(item[0]);
                    cvs.setSourcePort(item[1]);
                    cvs.setTargetName(item[2]);
                    cvs.setTargetPort(item[3]);
                } else {
                    //第一个是交换机， 第三个不存在， 无效链路
                    successEdge = false;
                }
            }
        } else {
            if(serverList0.size()>0) {
                //第一条线是服务器
                if(switchList3.size()>0) {
                    //第一条是服务器 第三条是交换机
                    cvs.setEdgeType(1);
                    cvs.setSourceId(switchList3.get(0).getId());
                    cvs.setTargetId(serverList0.get(0).getId());
                    cvs.setLabId(serverList0.get(0).getLabId());
                    cvs.setSourceName(item[2]);
                    cvs.setSourcePort(item[3]);
                    cvs.setTargetName(item[0]);
                    cvs.setTargetPort(item[1]);
                } else {
                   if(serverList3.size()>0) {
                       //第一条线是服务器,第三条是服务器 ， 链路不存在
                       successEdge = false;
                   } else{
                       //第一条线是服务器， 第三条不是交换机或服务器 链路不存在
                       successEdge = false;
                   }
                }
            } else {
                //第一条不是交换机也不是服务器，不存在无效链路
                successEdge = false;
            }
        }
        return successEdge;
    }

    private boolean compareName(String name1, String name2) {
        if(name1.contains("/")) {
            String prefix = name1.substring(0,name1.lastIndexOf('/')-1);
            String[] numArray = name1.substring(name1.lastIndexOf('/')-1).split("/");
            for(String num : numArray) {
                if(name2.equalsIgnoreCase(prefix+num)) {
                    return true;
                }
            }
            return false;
        } else {
            return name1.equalsIgnoreCase(name2);
        }
    }

    /*
     * 将vlan 转换成数组
     * @param vlan
     * @return
     */
    private List<Integer> conversArray(String vlan) {
        List<Integer> result = new ArrayList<>();
        if(!StringUtils.isEmpty(vlan)) {
            String[] vlanList = vlan.split(";");
            for(String lan : vlanList) {
                if(lan.contains("-")) {
                    String[] range = lan.split("-");
                    for(int i=Integer.parseInt(range[0]); i<=Integer.parseInt(range[1]); i++) {
                        result.add(i);
                    }
                } else {
                    result.add(Integer.parseInt(lan));
                }
            }
        }
        return result;
    }

    /*
     * 如果源端节点名=对端节点名
     * @param cvsList
     */
    private List<Cvs> removeInvalidRecord(List<Cvs> cvsList) {
        List<Cvs> newCvsList = new ArrayList<>();
        for(int i=0;i<cvsList.size(); i++) {
            Cvs cvs = cvsList.get(i);
            if(!cvs.getSourceName().equalsIgnoreCase(cvs.getTargetName())) {
                newCvsList.add(cvs);
            }
        }
        return newCvsList;
    }

    private List<Cvs> removeRepeatRecord(List<Cvs> cvsList) {
        List<Cvs> result = new ArrayList<>();
       for(int i=0; i<cvsList.size(); i++) {
           Cvs currCvs = cvsList.get(i);
           if(!result.contains(currCvs)) {
               boolean repeat = false;
               List<Cvs> repeatList = new ArrayList<>();
               for(int j=i+1; j<cvsList.size(); j++) {
                   Cvs compareCvs = cvsList.get(j);
                   if(currCvs.equals(compareCvs)) {
                       repeatList.add(compareCvs);
                       repeat = true;
                   }
               }
               if(repeat) {
                   repeatList.add(currCvs);
                   //vlan 取交集
                   List<Integer> intersectionList = new ArrayList<>();
                   for(int j=0; j<repeatList.size(); j++) {
                       List<Integer> subvlan = repeatList.get(j).getVlan();
                       if(j==0) {
                           intersectionList = subvlan;
                       } else {
                           intersectionList = intersectionList.stream().filter(item -> subvlan.contains(item)).collect(Collectors.toList());
                       }
                   }
                   currCvs.setVlan(intersectionList);
                   result.add(currCvs);
               } else {
                   result.add(currCvs);
               }
           }

       }
       return result;
    }

}
